﻿using System.Windows;

namespace SHomeWorkshop.LunarPresentation.Commands
{
    public partial class Command
    {
        /// <summary>
        /// 自动卷动编辑器的ScrollViewer，来显示不在可视区的公式。
        /// 此方法应在“公式被选中”后调用。
        /// 注意：“插入并编辑文本块”不应调用此方法——因为此方法未考虑文本块编辑器的位置。
        /// </summary>
        /// <param name="ex">目标公式。</param>
        public static void AutoLocation(Expressions.Expression ex)
        {
            if (ex == null) return;
            if (ex.Editor == null) return;
            if (ex.Editor.IsOpened == false) return;
            if (ex.Editor != Globals.selectedEditor) return;
            if (ex.Parent == null) return;//可能不在可视树。
            //if (ex.IsVisibleInScrollviewer == false) return;

            Globals.isDraging = false;
            if (Globals.dragSourceExpression != null) Globals.dragSourceExpression = null;

            ex.InvalidateArrange();
            ex.UpdateLayout();//不加这两句，新插入公式时定位会出问题。

            double currentVOffcet = ex.Editor.BaseScrolledViewer.VerticalOffset;
            double currentHOffcet = ex.Editor.BaseScrolledViewer.HorizontalOffset;

            Point ptBase = new Point(0, 0);
            Point ptEx = ex.PointToScreen(ptBase);
            Point ptSV = ex.Editor.BaseScrolledViewer.PointToScreen(ptBase);

            double rightOfScrollviewer = ptSV.X + ex.Editor.BaseScrolledViewer.ActualWidth;
            double rightOfBaseText = ptEx.X + ex.Editor.SelectedExpression.ActualWidth;
            
            Rect exRect = new Rect(ptEx, new Point(ptEx.X + ex.ActualWidth, ptEx.Y + ex.ActualHeight));
            Rect svRect = new Rect(ptSV, new Point(ptSV.X + ex.Editor.BaseScrolledViewer.ActualWidth - 24,
                ptSV.Y + ex.Editor.BaseScrolledViewer.ActualHeight - 24));//24是滚动条的宽度。

            //如果公式宽、高都小于可视区。
            if (exRect.Width < svRect.Width && exRect.Height < svRect.Height)
            {
                //第一种情况。公式部分或全部在可视区左上角且不可全见或不可见。
                if (exRect.Top < svRect.Top && exRect.Left < svRect.Left)
                {
                    //定位到编辑区左上角。
                    ex.Editor.BaseScrolledViewer.
                        ScrollToHorizontalOffset(currentHOffcet - (svRect.Left - exRect.Left) - 4);
                    ex.Editor.BaseScrolledViewer.
                        ScrollToVerticalOffset(currentVOffcet - (svRect.Top - exRect.Top));
                }
                //第二种情况。公式部分或全部在可视区右上角且不可全见或不可见。
                else if (exRect.Right > svRect.Right && exRect.Top < svRect.Top)
                {
                    //定位到右上角。
                    ex.Editor.BaseScrolledViewer.
                        ScrollToHorizontalOffset(currentHOffcet + (exRect.Right - svRect.Right));
                    ex.Editor.BaseScrolledViewer.
                        ScrollToVerticalOffset(currentVOffcet - (svRect.Top - exRect.Top) - 4);
                }
                //第三种情况。公式部分或全部在可视区左下角且不可全见或不可见。
                else if (exRect.Bottom > svRect.Bottom && exRect.Left < svRect.Left)
                {
                    //定位到左下角。
                    ex.Editor.BaseScrolledViewer.
                        ScrollToHorizontalOffset(currentHOffcet - (svRect.Left - exRect.Left) - 4);
                    ex.Editor.BaseScrolledViewer.
                        ScrollToVerticalOffset(currentVOffcet + (exRect.Bottom - svRect.Bottom));
                }
                //第四种情况。公式部分或全部在可视区右下角且不可全见或不可见。
                else if (exRect.Bottom > svRect.Bottom && exRect.Right > svRect.Right)
                {
                    //定位到右下角。
                    ex.Editor.BaseScrolledViewer.
                        ScrollToHorizontalOffset(currentHOffcet + (exRect.Right - svRect.Right));
                    ex.Editor.BaseScrolledViewer.
                        ScrollToVerticalOffset(currentVOffcet + (exRect.Bottom - svRect.Bottom));
                }
                //第五种情况。公式部分或全部在可视区左侧且不可全见或不可见。
                else if (exRect.Left < svRect.Left && exRect.Top > svRect.Top)
                {
                    //定位到左侧。
                    ex.Editor.BaseScrolledViewer.
                        ScrollToHorizontalOffset(currentHOffcet - (svRect.Left - exRect.Left) - 4);
                }
                //第六种情况。公式部分或全部在可视区上侧且不可全见或不可见。
                else if (exRect.Left > svRect.Left && exRect.Top < svRect.Top)
                {
                    //定位到上侧。
                    ex.Editor.BaseScrolledViewer.
                        ScrollToVerticalOffset(currentVOffcet - (svRect.Top - exRect.Top) - 4);
                }
                //第七种情况。公式部分或全部在可视区右侧且不可全见或不可见。
                else if (exRect.Right > svRect.Right && exRect.Top > svRect.Top)
                {
                    //定位到右侧
                    ex.Editor.BaseScrolledViewer.
                        ScrollToHorizontalOffset(currentHOffcet + (exRect.Right - svRect.Right));
                }
                //第八种情况。公式部分或全部在可视区下侧且不可全见或不可见。
                else if (exRect.Bottom > svRect.Bottom && exRect.Left > svRect.Left)
                {
                    //定位到下侧。
                    ex.Editor.BaseScrolledViewer.
                        ScrollToVerticalOffset(currentVOffcet + (exRect.Bottom - svRect.Bottom));
                }
                //第九种情况。公式就在可视区，不进行任何操作。
            }
            else
            {
                //如果高、宽有一个小，而另一个大于可视区
                if (exRect.Width < svRect.Width)
                {
                    if (exRect.Left < svRect.Left)
                    {
                        ex.Editor.BaseScrolledViewer.
                        ScrollToHorizontalOffset(currentHOffcet - (svRect.Left - exRect.Left) - 4);
                    }
                    else if (exRect.Right > svRect.Right)
                    {
                        ex.Editor.BaseScrolledViewer.
                        ScrollToHorizontalOffset(currentHOffcet + (exRect.Right - svRect.Right));
                    }
                }

                if (exRect.Height < svRect.Height)
                {
                    if (exRect.Top < svRect.Top)
                    {
                        ex.Editor.BaseScrolledViewer.
                        ScrollToVerticalOffset(currentVOffcet - (svRect.Top - exRect.Top) - 4);
                    }
                    else if (exRect.Bottom > svRect.Bottom)
                    {
                        ex.Editor.BaseScrolledViewer.
                        ScrollToVerticalOffset(currentVOffcet + (exRect.Bottom - svRect.Bottom));
                    }
                }
            }
        }
    }
}
